package com.mc.fastkit.widget

import android.app.Activity
import android.app.Application
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.mc.fastkit.callback.SimpleActivityLifecycleCallbacks
import com.mc.fastkit.ext.app
import com.mc.fastkit.ext.cast
import java.util.Stack

/**
 * Activity栈管理
 * @author: MasterChan
 * @date: 2023-02-23 22:35
 */
class ActivityStack {

    /**
     * 缓存Activity，先进后出
     */
    private val stack = Stack<Activity>()

    /**
     * App是否在前台
     */
    var isAppForeground = false
        private set

    /**
     * 栈顶的Activity，即目前交互的Activity
     */
    val top: Activity?
        get() = runCatching { stack.lastElement() }.getOrNull()

    /**
     * 栈底的Activity
     */
    val bottom: Activity?
        get() = runCatching { stack.firstElement() }.getOrNull()

    /**
     * 栈中所有Activity
     */
    val all: List<Activity>
        get() = stack

    private val lifecycleCallback = Callbacks()
    private val stateChangedListeners by lazy { mutableListOf<OnAppStateChangedListener>() }

    companion object {
        val instance by lazy { ActivityStack() }
    }

    fun interface OnAppStateChangedListener {
        fun onStateChanged(isForeground: Boolean, activity: Activity)
    }

    fun init(app: Application) {
        app.registerActivityLifecycleCallbacks(lifecycleCallback)
    }

    /**
     * Activity是否已经在App中打开，即是否已经加入到栈中
     * @param activity Activity
     * @return Boolean
     */
    fun isLaunch(activity: Activity?): Boolean {
        return stack.contains(activity)
    }

    /**
     * Activity是否已经在App中打开，即是否已经加入到栈中
     * @param clazz Class<Activity>
     * @return Boolean
     */
    fun isLaunch(clazz: Class<out Activity>): Boolean {
        return indexOf(clazz) >= 0
    }

    /**
     * 关闭Activity
     * @param clazz Class<Activity>
     */
    fun finish(clazz: Class<out Activity>) {
        getActivity(clazz)?.finish()
    }

    /**
     * 关闭栈中的所有Activity
     * @param fromBottom 是否栈底开始关闭；true：从栈底开始，false：从栈顶开始
     */
    fun finishAll(fromBottom: Boolean = true) {
        if (fromBottom) {
            stack.forEach { it.finish() }
        } else {
            stack.reversed().forEach { it.finish() }
        }
    }

    /**
     * 根据[clazz]获取对应的Activity，如果栈中不存在则返回null
     * @param clazz Class<Activity>
     * @return Activity?
     */
    fun <T : Activity> getActivity(clazz: Class<out T>): T? {
        val index = indexOf(clazz)
        if (index < 0) return null
        return stack[index].cast()
    }

    /**
     * 获取Activity在栈中的索引，从栈底开始计数，如果Activity不在栈中，返回-1
     * @param activity Activity
     * @return Int
     */
    fun indexOf(activity: Activity): Int {
        return stack.indexOfFirst { it == activity }
    }

    /**
     * 获取Activity在栈中的索引，从栈底开始计数，如果Activity不在栈中，返回-1
     * @param clazz Class<out Activity>
     * @return Int
     */
    fun indexOf(clazz: Class<out Activity>): Int {
        return stack.indexOfFirst { it.javaClass == clazz }
    }

    /**
     * 添加App前后台状态改变监听
     * @param listener OnAppStateChangedListener
     */
    fun addOnAppStateChangedListener(listener: OnAppStateChangedListener) {
        stateChangedListeners.add(listener)
    }

    fun addOnAppStateChangedListener(
        activity: ComponentActivity,
        listener: OnAppStateChangedListener
    ) {
        activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onDestroy(owner: LifecycleOwner) {
                stateChangedListeners.remove(listener)
            }
        })
        stateChangedListeners.add(listener)
    }

    fun addOnAppStateChangedListener(
        fragment: Fragment,
        listener: OnAppStateChangedListener
    ) {
        fragment.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onDestroy(owner: LifecycleOwner) {
                stateChangedListeners.remove(listener)
            }
        })
        stateChangedListeners.add(listener)
    }

    /**
     * 移除App前后台状态改变监听
     * @param listener OnAppStateChangedListener
     */
    fun removeAppStateChangedListener(listener: OnAppStateChangedListener) {
        stateChangedListeners.remove(listener)
    }

    private inner class Callbacks : SimpleActivityLifecycleCallbacks() {

        private var activityCount = 0

        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            stack.add(activity)
        }

        override fun onActivityStarted(activity: Activity) {
            activityCount++
            if (activityCount == 1) {
                setAppState(true, activity)
            }
        }

        override fun onActivityStopped(activity: Activity) {
            activityCount--
            if (activityCount == 0) {
                setAppState(false, activity)
            }
        }

        override fun onActivityDestroyed(activity: Activity) {
            stack.remove(activity)
        }

        private fun setAppState(isForeground: Boolean, activity: Activity) {
            isAppForeground = isForeground
            stateChangedListeners.forEach { it.onStateChanged(isForeground, activity) }
        }
    }

    fun unInit() {
        app.unregisterActivityLifecycleCallbacks(lifecycleCallback)
    }
}